package org.vison.wonfu.framework.log;

import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggerConfiguration;
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.Environment;
import org.vison.wonfu.framework.config.ConfigAutoConfigure;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Configuration
public class LogAutoConfigure {

    private static final Logger logger = LoggerFactory.getLogger(LogAutoConfigure.class);
    private static final String NAMESPACE = "application"; // Apollo命名空间
    private static final String LOGGING_PREFIX = "logging.level.";

    private final LoggingSystem loggingSystem;
    private final ConfigurableEnvironment environment;

    @PostConstruct
    public void init() {
        // 从Apollo获取配置并设置日志级别
        initLoggingLevels();
        List<LoggerConfiguration> loggerConfigurations = loggingSystem.getLoggerConfigurations();
        logger.info("日志级别初始化完成");
    }

    public LogAutoConfigure(LoggingSystem loggingSystem,ConfigurableEnvironment environment) {
        this.loggingSystem = loggingSystem;
        this.environment = environment;
    }

    // 监听Apollo配置变化
    @ApolloConfigChangeListener(value = NAMESPACE)
    public void onChange(ConfigChangeEvent changeEvent) {
        changeEvent.changedKeys().forEach(key -> {
            if (key.startsWith(LOGGING_PREFIX)) {
                String loggerName = key.substring(LOGGING_PREFIX.length());
                String levelStr = environment.getProperty(key, "INFO");
                LogLevel level = LogLevel.valueOf(levelStr.toUpperCase());
                logger.info("日志级别已更新 key: {} old: {} new: {}", loggerName,
                        changeEvent.getChange(key).getOldValue(), level);
                loggingSystem.setLogLevel(loggerName, level);
            }
        });
    }

    /**
     * 从Environment中获取日志级别配置，刷新日志级别
     */
    private void initLoggingLevels() {
        List<String> loggingLevelConfigs = new ArrayList<>();
        // 遍历所有配置源（PropertySource）
        environment.getPropertySources().forEach(propertySource -> {
            // 仅处理可枚举的配置源（能获取所有属性名）
            if (propertySource instanceof EnumerablePropertySource) {
                EnumerablePropertySource<?> enumerableSource = (EnumerablePropertySource<?>) propertySource;
                // 获取当前配置源的所有属性键
                String[] propertyNames = enumerableSource.getPropertyNames();

                for (String key : propertyNames) {
                    // 筛选前缀为 "logging.level." 的键
                    if (key.startsWith(LOGGING_PREFIX)) {
                        // 通过Environment获取最终生效的值（考虑配置源优先级覆盖）
                        String value = environment.getProperty(key, "INFO");
                        loggingLevelConfigs.add(key + "=" + value);
                        String loggerName = key.substring(LOGGING_PREFIX.length());
                        loggingSystem.setLogLevel(loggerName, LogLevel.valueOf(value.toUpperCase()));
                    }
                }
            }
        });
        logger.info("当前日志级别配置: {}", loggingLevelConfigs);
    }


    /**
     * 简单判断Logger名称是否为类的全限定名（非包名、非root）
     */
    private boolean isClassName(String loggerName) {
        // 排除root Logger
        if ("root".equals(loggerName)) {
            return false;
        }
        // 类名最后一段通常包含大写字母（如com.example.UserService）
        String[] parts = loggerName.split("\\.");
        if (parts.length == 0) {
            return false;
        }
        String lastPart = parts[parts.length - 1];
        return !lastPart.equals(lastPart.toLowerCase()); // 包含大写字母则视为类名
    }
}
